<template>
  <!-- <component :is="defaults[0]"></component> -->
  <!-- <div v-for="t in titles" :key="t">{{ t }}</div> -->
  <!-- <component v-for="(c, index) in defaults" :is="c" :key="index"></component> -->

  <div class="h-tabs">
    <div class="h-tabs-nav" ref="container">
      <div
        class="h-tabs-nav-item"
        v-for="(t, index) in titles"
        :key="index"
        :class="{ selected: t === selected }"
        @click="select(t)"
        :ref="
          (el) => {
            if (t === selected) selectedItem = el
          }
        "
      >
        {{ t }}
      </div>
      <div class="h-tabs-nav-indicator" ref="indicator"></div>
    </div>
    <div class="h-tabs-content">
      <component :is="current" :key="current.props.title" />
    </div>
  </div>
</template>

<script lang="ts">
import { computed, onMounted, onUpdated, ref, watchEffect } from 'vue'
import HTab from './HTab.vue'

export default {
  props: {
    selected: {
      type: String,
    },
  },
  setup(props, context) {
    // 判断Tabs子标签必须是Tab组件
    const defaults = context.slots.default()
    defaults.forEach((tag) => {
      if (tag.type !== HTab) {
        throw new Error('Tabs子标签必须是Tab')
      }
    })

    const titles = defaults.map((t) => t.props.title)

    const current = computed(() => {
      return defaults.find((tag) => tag.props.title === props.selected)
    })

    const select = (title) => {
      context.emit('update:selected', title)
    }

    // 计算下划线长度
    const selectedItem = ref<HTMLDivElement>(null)
    const indicator = ref<HTMLDivElement>(null)
    const container = ref<HTMLDivElement>(null)

    const x = () => {
      const { width, left: left2 } = selectedItem.value.getBoundingClientRect()
      indicator.value.style.width = width + 'px'
      const { left: left1 } = container.value.getBoundingClientRect()
      const left = left2 - left1
      indicator.value.style.left = left + 'px'
    }
    onMounted(() => {
      // 注意要在元素挂载后才能获取其宽度。
      // 使用 watch 来监听每次点击时更改下划线位置与宽度。
      watchEffect(
        () => {
          const {
            width,
            left: left2,
          } = selectedItem.value.getBoundingClientRect()
          indicator.value.style.width = width + 'px'
          const { left: left1 } = container.value.getBoundingClientRect()
          const left = left2 - left1
          indicator.value.style.left = left + 'px'
        },
        { flush: 'post' }
      )
    })

    return {
      defaults,
      titles,
      current,
      select,
      selectedItem,
      indicator,
      container,
    }
  },
}
</script>

<style lang="scss">
$blue: #40a9ff;
$color: #333;
$border-color: #d9d9d9;
.h-tabs {
  &-nav {
    display: flex;
    color: $color;
    border-bottom: 1px solid $border-color;
    position: relative;
    &-item {
      padding: 8px 0;
      margin: 0 16px;
      cursor: pointer;
      &:first-child {
        margin-left: 0;
      }
      &.selected {
        color: $blue;
      }
    }
    &-indicator {
      position: absolute;
      height: 3px;
      background: $blue;
      left: 0;
      bottom: -1px;
      width: 100px;
      transition: all 500ms;
    }
  }
  &-content {
    padding: 8px 0;
  }
}
</style>
